#include "database.h"
#include <cstring>
#include <algorithm>

using namespace std;

//给数据文件和索引文件初始化，在给定文件名后加上后缀
SimpleDatabase::SimpleDatabase(const string& base_filename) 
    : data_filename("../data/" + base_filename + ".dat"), 
      index_filename("../data/" + base_filename + ".idx"),
      bplus_tree(nullptr) 
    {
        // todo to be implemented
        std::cout << "SimpleDatabase::SimpleDatabase(" << base_filename + ".dat" 
        <<"," << base_filename + ".idx" << ")" << std::endl;
    }

//变量生命周期结束自动销毁数据库
SimpleDatabase::~SimpleDatabase() {
    destory();
}

void SimpleDatabase::init() {
    // todo to be implemented
    std::cout << "SimpleDatabase::init() ..." << std::endl;

    //存在则直接打开
    data_file.open(data_filename, ios::binary | ios::in | ios::out | ios::ate);
    if (!data_file.is_open()) {
        //不存在创建在打开
        //创建不存在的文件时不能带ios::in所以只能先创建关闭后，用读写加追加的方式打开
        data_file.open(data_filename, ios::binary | ios::out);
        data_file.close();
        data_file.open(data_filename, ios::binary | ios::in | ios::out | ios::ate);
    }

    //让B+树关联上索引文件
    bplus_tree = new BPlusTree(index_filename);
}

void SimpleDatabase::destory() {
    // todo to be implemented
    std::cout << "SimpleDatabase::destory() ..." << std::endl;

    //先关闭文件防止remove失败
    if (data_file.is_open()) data_file.close();
    if (bplus_tree) {
        delete bplus_tree;
        bplus_tree = nullptr;
    }

    //标准库中的remove永久删除磁盘中的文件
    std::remove(data_filename.c_str());
    std::remove(index_filename.c_str());
}

bool SimpleDatabase::add(const vector<Record>& records) {
    // todo to be implemented
    std::cout << "SimpleDatabase::add ..." << std::endl;

    for (const auto& rec : records) {
        string name = rec.name;
        string desc = rec.desc;

        //因为是定长，所以稍作处理，方便后面写入
        fix_string(name, NAME_LEN);
        fix_string(desc, DESC_LEN);

        //根据id算出偏移量，找到该插入的位置
        long long offset = get_data_offset(rec.id);
        //移动文件的写入指针，位置是从文件头开始偏移offset
        data_file.seekp(offset, ios::beg);
        //在正确的位置写入
        data_file.write(reinterpret_cast<const char*>(&rec.id), sizeof(int));
        data_file.write(name.c_str(), NAME_LEN);
        data_file.write(desc.c_str(), DESC_LEN);

        //插入id与偏移量offset的键值对索引
        bplus_tree->insert(rec.id, offset);
    }
    return true;
}

bool SimpleDatabase::remove(const vector<int>& ids) {
    // todo to be implemented
    std::cout << "Removing records from database ..." << std::endl;

    for (int id : ids) {
        long long offset;
        //根据id直接在B+树中映射找到offset，且是存在则删除，不存在跳过
        if (bplus_tree->find(id, offset)) {
            data_file.seekp(offset, ios::beg);
            //删除并不真的清空数据，而是将id置为-1
            //如果真的清除可能需要挪动后续数据那么id和offset就会发生改变，牵一发而动全身不值得
            //置为-1，在B+树中仅需删除映射关系，在数据文件中后续若有一样的id直接覆盖即可
            int deleted_id = -1;
            data_file.write(reinterpret_cast<const char*>(&deleted_id), sizeof(int));
            bplus_tree->remove(id);
        }
    }
    return true;
}

bool SimpleDatabase::update_name(int id, const std::string& new_name) {
    // todo to be implemented
    std::cout << "SimpleDatabase::update_name ..." << std::endl;

    long long offset;
    //不存在则更新失败
    if (!bplus_tree->find(id, offset)) return false;

    //找到位置后继续向后偏移id的大小找到name
    data_file.seekp(offset + sizeof(int), ios::beg);
    string name = new_name;
    fix_string(name, NAME_LEN);
    data_file.write(name.c_str(), NAME_LEN);
    return true;
}

bool SimpleDatabase::find_record_by_id(int id, Record& result) {
    // todo to be implemented
    std::cout << "SimpleDatabase::find_record_by_id ..." << std::endl;

    long long offset;
    //也是id不存在则查找失败
    if (!bplus_tree->find(id, offset)) return false;

    data_file.seekg(offset, ios::beg);
    int read_id;
    data_file.read(reinterpret_cast<char*>(&read_id), sizeof(int));
    //如果id是-1说明这条记录其实已经被删除了，所以也是查找失败
    if (read_id == -1) return false;

    char name[NAME_LEN + 1] = {0};
    char desc[DESC_LEN + 1] = {0};
    data_file.read(name, NAME_LEN);
    data_file.read(desc, DESC_LEN);

    result.id = read_id;
    result.name = name;
    result.desc = desc;
    return true;
}

vector<Record> SimpleDatabase::find_records_in_range(int min_id, int max_id) {
    // todo to be implemented
    std::cout << "SimpleDatabase::find_records_in_range ..." << std::endl;

    //启用B+树的范围查找，得到所有符合要求id的offset
    vector<long long> offsets = bplus_tree->range_query(min_id, max_id);
    vector<Record> result;

    //类似于点查，循环获得所有符合要求的记录存放到vector<Record>中
    for (long long offset : offsets) {
        data_file.seekg(offset, ios::beg);
        int id;
        data_file.read(reinterpret_cast<char*>(&id), sizeof(int));
        if (id == -1) continue;

        char name[NAME_LEN + 1] = {0};
        char desc[DESC_LEN + 1] = {0};
        data_file.read(name, NAME_LEN);
        data_file.read(desc, DESC_LEN);
        result.emplace_back(id, name, desc);
    }
    return result;
}

// 前缀查询（遍历所有叶子节点）
vector<Record> SimpleDatabase::find_records_by_name_prefix(const std::string &prefix) {
    // todo to be implemented
    std::cout << "SimpleDatabase::find_records_by_name_prefix ..." << std::endl;

    vector<Record> result;
    if (prefix.empty()) return result;

    // 从根节点开始循环向下找，直至找到第一个叶子节点（即最左叶子结点）
    long long current_offset = bplus_tree->get_root();
    BPlusTreeNode current_node;
    while (true) {
        bplus_tree->read_node(current_offset, current_node);
        if (current_node.is_leaf) break;
        current_offset = current_node.children[0];
    }

    // 遍历所有叶子节点（利用类似于链表，即BPlusTreeNode中的next_leaf）
    while (current_offset != -1) {
        //外层循环调整至下一个叶子结点
        bplus_tree->read_node(current_offset, current_node);
        for (int i = 0; i < current_node.key_count; i++) {
            //内层循环遍历某一个结点
            int id = current_node.keys[i];
            long long data_offset = current_node.children[i];

            // 读取记录并检查前缀
            data_file.seekg(data_offset, ios::beg);
            int read_id;
            data_file.read(reinterpret_cast<char*>(&read_id), sizeof(int));
            if (read_id == -1) continue; // 跳过已删除记录

            char name[NAME_LEN + 1] = {0};
            data_file.read(name, NAME_LEN);
            if (string(name).substr(0, prefix.size()) == prefix) {
                char desc[DESC_LEN + 1] = {0};
                data_file.read(desc, DESC_LEN);
                result.emplace_back(id, name, desc);
            }
        }
        // 下一个叶子节点
        current_offset = current_node.next_leaf;
    }
    return result;
}

bool SimpleDatabase::truncate() {
    // todo to be implemented
    std::cout << "SimpleDatabase::truncate() ..." << std::endl;

    destory();
    init();
    return true;
}